
// In the body of the functions that follow we might want to use macros based on the following conventions to facilitate debugging.

// There is a variable or macro K indicating the nubmer of blocks. 
// There is a variable or macro N that yields the size of the matrix.
// There is a macro BS that yields N/K, that is, the size of a block. N must be a multiple of K to keep everything simple.

// And so it follows.
#define K 10
#define BS (N/K)

// Accessing an element in a matrix is done with :
#define MATACC(A,i,j) (A[(i)*N+(j)])

// For accessing blocks, we suppose I and J, the block coordinates, are defined already.
#define BLOCKACC(A,i,j) MATACC(A,i+(I*BS),j+J*(BS))


// Plan : multiply by block of size K
//  M -> K^2 blocks of access for summing, K^3 combinations ( by pointers )

// There are several tasks here :
//  Main : creates two matrixes, fills them with rand numbers.
//        creates a buffer for the result.
//        launches the computations on the matrix and then checks the results.
//  Entry : Creates K^3 multipliers
//			Creates K^3 adders.
//  Multiplier : allocates memory
//				 computes  block C(I,J,k)
// 				 Wakes all adders waiting for it.
//  Adder : waits for a C(I,J,K), adds it in place in block I,J, unsing OWM acquire.
//          -> test of OWM : since only one output buffer exists, lots of contention will occur, good for testing.
//			then frees the OWM.

#define N 100
#define K 10


void matmul( int *  a, int * b, int * c ) {
	for ( int i = 0; i < N; ++i ) {
		for ( int j = 0; j < N; ++j ) {
			MATACC( c, i , j ) = 0;
			for ( int k = 0; k < N; ++ k ) {
				MATACC( c,i,j ) += MATACC( a,i,k ) * MATACC(b,k,j );
			}
		}
	}

}


struct blockmul_task_frame {
	struct blockmul_task_infos * infos;
	int sc;
	struct waiter_frame_struct * out;
	int I;
	int J;
	int K;
};

void blockmul_task() {
	// Get I,J,K
	int I = fp->I;
	int J = fp->J;
	int K = fp->K;
	


	int * retb = calloc( BS*BS, sizeof(int));
	for ( int i = 0; i < BS; ++ i ) {
		for ( int j = 0; j < BS; ++ j ) {
			for ( int k = 0; k < BS; ++k ) {
				MATACC( retb,i,j ) += MATACC( a, I*BS+i,K*BS+k) * MATACC(b,K*BS+k,J*BS+j)
				
			}
		}
	}

	// RETURN RESULT :
	// Create write descriptor.
	data[K] = k /* Important problem of genericity :p */
}
